#ifndef _AUDIO_SCENE_H
#define _AUDIO_SCENE_H

#include <stdint.h>

#include "FreeRTOS.h"
#include "task.h"

#include "audio_common.h"
#include "audio_hw.h"
#include "audio_decoder.h"
#include "audio_encoder.h"

typedef uint32_t (*audio_scene_decoder_req_raw_cb)(uint8_t *data, uint32_t length);

typedef enum {
    /*===============  Internal Usage or Common Event ==============*/
    AUDIO_SCENE_EVT_TYPE_CREATE,
    AUDIO_SCENE_EVT_TYPE_DESTROY,
    /* new encoded frame is received, such as sbc frame received from a2dp source */
    AUDIO_SCENE_EVT_TYPE_RECV_ENCODED_FRAME,
    /* decoder request more raw data */
    AUDIO_SCENE_EVT_TYPE_REQ_ENCODED_FRAME,
    /* audio hardware working in AUDIO_HW_DIR_IN mode receive new PCM data */
    AUDIO_SCENE_EVT_TYPE_HW_IN_NEW_SAMPLES,

//    AUDIO_SCENE_EVT_TYPE_TONE_ADD,
//    AUDIO_SCENE_EVT_TYPE_TONE_REMOVE,
    
    AUDIO_SCENE_EVT_YTPE_MAX,
} audio_scene_evt_type_t;

typedef struct audio_scene_operator audio_scene_operator_t;

typedef struct {
    void *env;
    void *param;
    audio_scene_operator_t *op;
} audio_scene_t;

typedef struct {
    struct co_list_hdr hdr;
    
    audio_scene_evt_type_t type;
    audio_scene_t *scene;
} audio_scene_evt_t;

/* event for AUDIO_SCENE_EVT_TYPE_REQ_ENCODED_FRAME */
typedef struct {
    audio_scene_evt_t evt;
    audio_decoder_t *decoder;
} audio_scene_evt_req_encoded_frame_t;

/* event for AUDIO_SCENE_EVT_TYPE_HW_IN_NEW_SAMPLES */
typedef struct {
    audio_scene_evt_t evt;
    uint32_t adc_new_samples;
} audio_scene_evt_hw_in_new_samples_t;

/* event for AUDIO_SCENE_EVT_TYPE_TONE_ADD */
typedef struct {
    audio_scene_evt_t evt;
    audio_type_t audio_type;
    audio_scene_decoder_req_raw_cb cb;
} audio_scene_evt_tone_add_t;

typedef struct {
    audio_scene_evt_t evt;
    audio_data_element_t *raw_frame;
} audio_scene_evt_recv_encoded_data_t;

struct audio_scene_operator {
    audio_scene_t *(*allocate)(void *param);
    void (*init)(audio_scene_t *);
    void (*destroy)(audio_scene_t *);
    void (*event_handler)(audio_scene_t *, audio_scene_evt_t *evt);
    bool (*decoder_started)(audio_scene_t *);
    
    bool support_tone;
};

typedef struct {
    audio_type_t audio_type;
    audio_decoder_param_t decoder_param;
    
    audio_hw_type_t hw_type;
    uint32_t hw_base_addr;
    uint8_t channels;
    uint32_t sample_rate;
    audio_scene_decoder_req_raw_cb req_raw_cb;
} audio_tone_param_t;

void audio_scene_init(uint32_t stack_size, uint8_t priority);

audio_scene_t *audio_scene_create(audio_scene_operator_t *op, void *param);
void audio_scene_destroy(audio_scene_t *scene);
void audio_scene_send_event(audio_scene_evt_t *event);

void audio_scene_recv_encoded_data(audio_scene_t *scene, bool valid, const uint8_t *buffer, uint32_t length);
bool audio_scene_decoder_started(audio_scene_t *scene);

audio_scene_t *audio_scene_tone_play(audio_tone_param_t *param);
void audio_scene_tone_stop(void);

#endif  // _AUDIO_SCENE_H
